package com.sduept.nwld.dataserver.controller.equipment.assessment;

import com.sduept.bigdata.equipment.assessment.dto.expert.ExpertTreeTableDTO;
import com.sduept.bigdata.equipment.assessment.model.inspection.InspectionExpert;
import com.sduept.bigdata.equipment.assessment.model.inspection.InspectionStation;
import com.sduept.bigdata.equipment.assessment.service.InspectionExpertService;
import com.sduept.bigdata.equipment.assessment.service.InspectionStationService;
import com.sduept.bigdata.web.jsf.controller.AbstractController;
import com.sduept.nwld.dataserver.util.LibTreeNode;
import com.sduept.permission.cache.PermissionDataCache;
import com.sduept.permission.entity.DepartmentEntityBean;
import com.sduept.permission.entity.PersonnelEntityBean;
import com.sduept.permission.manager.DepartManager;
import com.sduept.utils.PingYinUtil;
import org.apache.commons.lang3.StringUtils;
import org.primefaces.event.NodeExpandEvent;
import org.primefaces.event.NodeSelectEvent;
import org.primefaces.event.NodeUnselectEvent;
import org.primefaces.event.SelectEvent;
import org.primefaces.model.DefaultTreeNode;
import org.primefaces.model.TreeNode;
import org.springframework.beans.factory.annotation.Autowired;

import javax.annotation.PostConstruct;
import javax.faces.view.ViewScoped;
import javax.inject.Named;
import java.util.*;

@Named
@ViewScoped
public class ExpertController extends AbstractController {
	/**
	 * 
	 */
	private static final long serialVersionUID = 3907261915458428991L;
	
	@Autowired
	private DepartManager dm;
	@Autowired
	private InspectionExpertService expertService ;
	@Autowired
	private InspectionStationService stationService;
	
	private List<InspectionExpert> allExperts;//table显示的专家集合
	private InspectionExpert selected;//单项选择的专家
	private List<PersonnelEntityBean> personnels ;
	private Map<String, List<String>> personNameMap = new HashMap<>();  // 放人员首字母-全名
	private String searchExpert;//查询的专家名称
	private String personName;//从查询框选择的人员名
	private TreeNode root; // 组织机构树根节点-组织人员树
	private TreeNode treeTableRoot; //用于treeTable组件的专家root
	private TreeNode resetPersonTreeRoot;//用于重构人员树的treeRoot
	private TreeNode orgSelectedNode;
	private List<DepartmentEntityBean> deptRoots ;//根部门
	private boolean choiceStatus ;//判断是否继续选择的状态
	private Set<PersonnelEntityBean> checkboxPersons = new HashSet<PersonnelEntityBean>();
	private String alertMessage;//删除时的告警信息
	/**
	 * Map<专家,部门及其父部门集合>
	 */
	private Map<InspectionExpert,List<DepartmentEntityBean>> expertDeptNameMap;
	/**
	 * 根部门
	 */
	private DepartmentEntityBean rootDept = null;
	/**
	 * Map<部门,部门构造的树节点>
	 */
	private Map<DepartmentEntityBean,TreeNode> deptNodeMap;
 	@PostConstruct
	public void init() {
	    allExperts = expertService.findAll();
		deptRoots = dm.findRootDepts();
		if(deptRoots.size()>0) {
			rootDept = deptRoots.get(0);
		}
		initExpertDeptNameMap();
		initTree();
		initTreeTable();
	}
 	/**
 	 * 构造专家及其所有父部门的Map
 	 */
	private void initExpertDeptNameMap() {
		expertDeptNameMap = new HashMap<InspectionExpert, List<DepartmentEntityBean>>();
		for (InspectionExpert expert : allExperts) {
			List<DepartmentEntityBean> lt = getAllParentDept(expert);
			expertDeptNameMap.put(expert, lt);
		}
	}
	/**
	 * 获取专家的部门，以及部门的父部门，直到南方电网的下一级
	 * @param expert
	 * @return
	 */
	private List<DepartmentEntityBean> getAllParentDept(InspectionExpert expert) {
		List<DepartmentEntityBean> lt = new ArrayList<DepartmentEntityBean>();
		// 专家的直属部门id
		String directDeptId = expert.getDeptId();
		if(StringUtils.isEmpty(directDeptId)) {
			// 专家没有直属部门，将其归于到根部门上
			lt.add(rootDept);
		} else {
			// 专家有直属部门
			DepartmentEntityBean directDept = dm.findDepartmentById(directDeptId);
			lt = dm.recursiveFindParentDepartments(directDept);
			if(null == lt) {
				lt = new ArrayList<DepartmentEntityBean>();
			}
			lt.add(directDept);
		}
		return lt;
	}
	/**
	 * 构造treeTable
	 */
	private void initTreeTable() {
		deptNodeMap = new HashMap<DepartmentEntityBean, TreeNode>();
		treeTableRoot = new LibTreeNode("Root", null);
		String rootDeptName = "南方电网";
		if(null != rootDept) {
			rootDeptName = rootDept.getName();
		}
		//根部门--南方电网
		LibTreeNode orgRootNode = new LibTreeNode("dept", new ExpertTreeTableDTO(rootDeptName), treeTableRoot);
		deptNodeMap.put(rootDept, orgRootNode);
		for (InspectionExpert expert : expertDeptNameMap.keySet()) {
			List<DepartmentEntityBean> pDepts = expertDeptNameMap.get(expert);
			recursionGenTreeNode1(pDepts, 0, orgRootNode, expert);
		}
		orgRootNode.setExpanded(true);
	}
	/**
	 * 递归，将专家的父部门以及专家都在树中构造出来
	 */
	private void recursionGenTreeNode1(List<DepartmentEntityBean> list,int index,TreeNode pNode,InspectionExpert expert) {
		if(index >= list.size()) {
			new DefaultTreeNode("expert", new ExpertTreeTableDTO(expert.getName(), expert.getCode(), expert.getTelephone(), expert.getAddress(),expert.getIntroduce(),expert.getPosition()), pNode);
			return;
		}
		DepartmentEntityBean currentDept = list.get(index);
		if(deptNodeMap.containsKey(currentDept)) {
			index = index+1;
			pNode = deptNodeMap.get(currentDept);
			recursionGenTreeNode1(list, index, pNode, expert);
		} else {
			LibTreeNode currentNode = new LibTreeNode("dept", new ExpertTreeTableDTO(currentDept.getName()), pNode);
			deptNodeMap.put(currentDept, currentNode);
			recursionGenTreeNode1(list, index+1, currentNode, expert);
		}
	}
	
	/**
	 * 初始化组织机构树root
	 */
	private void initTree() {
		root = new LibTreeNode("Root", null);
		for (DepartmentEntityBean dept : deptRoots) {
			TreeNode orgRoot = new LibTreeNode("dept", dept, root);
			List<DepartmentEntityBean> ds = dm.getDepartmentsByParent(dept.getId()); // 默认展开一级
			for (DepartmentEntityBean d : ds) {
				 new LibTreeNode("dept", d, orgRoot);
			}
			List<PersonnelEntityBean> ps = dm.findDeptPersonnels(dept.getId());
			for (PersonnelEntityBean p : ps) {
				new DefaultTreeNode("personnel", p, orgRoot);
			}
			orgRoot.setExpanded(true);
		}
		resetPersonTreeRoot = root;
	}
	
	/**
	 * 组织机构树展开
	 * @param event
	 */
	public void onNodeExpand(NodeExpandEvent event) {
		if(StringUtils.isBlank(personName)) {
			TreeNode node = event.getTreeNode();
			if(!node.isSelected()) {
				node.getChildren().clear();
				DepartmentEntityBean dept = (DepartmentEntityBean) node.getData();
				List<DepartmentEntityBean> ds = dm.getDepartmentsByParent(dept.getId());
				for (DepartmentEntityBean d : ds) {
					 new LibTreeNode("dept", d, node);
				}
				List<PersonnelEntityBean> personnels = dm.findDeptPersonnels(dept.getId());
				if (personnels != null && personnels.size() > 0) {
					for (PersonnelEntityBean p : personnels) {
						DefaultTreeNode defaultNode = new DefaultTreeNode("personnel", p, node);
						if(checkboxPersons.contains(p)) {
							defaultNode.setSelected(true);
						}
					
					}
				}
			}
		}
	}
	
	/**
	 * 获得人员姓名拼音-姓名   map
	 * @param personnels
	 * @return
	 */
	private Map<String, List<String>> initPersonNameMap(List<PersonnelEntityBean> personnels) {
		Map<String, List<String>> map = new HashMap<String, List<String>>();
		for (PersonnelEntityBean personnelEntityBean : personnels) {
			String key  = PingYinUtil.getPingYinHeader(personnelEntityBean.getName());
			List<String> value =map.get(key);
			if(value==null) {
				value = new ArrayList<String>();
				map.put(key, value);
			}
			value.add(personnelEntityBean.getName());
		}
		return map;
	}
    /**
     * 人员查询框展开所有人员
     * @param query
     * @return
     */
    public List<String> completePersons(String query) {
    	List<String>  persons = new ArrayList<String>();
    	for (String s : personNameMap.keySet()) {
			if(s.startsWith(query)) {
				persons.addAll(personNameMap.get(s));
			}
		}
    	return persons;	
    }
   

	/**
     * 根据查询内容重新展示组织机构树
     * @param name
     */
	private void filterTree(String name) {
		PersonnelEntityBean selectPerson = new  PersonnelEntityBean();
		for (PersonnelEntityBean person : personnels) {
			if(person.getName().equals(name)) {
				selectPerson=person;
				break;
			}
		}
		DepartmentEntityBean selectDept = dm.findPersonDepart(selectPerson.getCode());//查到人就结束 然后一直递归到根
		root = new LibTreeNode("Root", null);//递归查询父部门 直到父部门为根部门  
		TreeNode childNode = new LibTreeNode("dept", selectDept, getParentDept(selectDept,root));
		childNode.setExpanded(true);
		TreeNode node = new DefaultTreeNode("personnel", selectPerson, childNode);
		node.setExpanded(true);
	}

     /**
      * 获得父部门  --组织机构树
      * @param selectDept
      * @param root2
      * @return
      */
	private TreeNode  getParentDept(DepartmentEntityBean selectDept, TreeNode root2) {
		DepartmentEntityBean  parentDept = selectDept.getParent();
		TreeNode treeNode = null;
		if(parentDept.getParent()!=null) {
			treeNode  = new LibTreeNode("dept", parentDept,getParentDept(parentDept,root2));
			treeNode.setExpanded(true);
		}else {
			treeNode  = new LibTreeNode("dept", parentDept,root2);
			treeNode.setExpanded(true);
		}
		return treeNode;
	}
	
	public void addExperts() {
		for(PersonnelEntityBean person: checkboxPersons) {
			boolean flag = false;
			for (InspectionExpert expert : allExperts) {
				if(person.getCode().equals(expert.getCode())) {
					flag = true;
					break;
				}
			}
			if(!flag) {
				saveExpert(person);
			}
		}
		addSuccessMessage("设为专家成功！");
	}
	
	private void saveExpert(PersonnelEntityBean person) {
		InspectionExpert expert = new InspectionExpert();
		expert.setCode(person.getCode());
		expert.setTelephone(person.getTelephone());
		expert.setName(person.getName());
		expert.setAddress(person.getAddress() );
		DepartmentEntityBean dept = person.getGroup();
		if(null!=dept) {
			expert.setDeptName(dept.getName());
			expert.setDeptId(dept.getId());
		}
		try {
			expert = expertService.createOrUpdate(expert);
			allExperts.add(expert);
			List<DepartmentEntityBean> lt = getAllParentDept(expert);
			expertDeptNameMap.put(expert, lt);
			initTreeTable();
		} catch (Exception e) {
			addErrorMessage("设置失败！");
			e.printStackTrace();
		}
	}
	/**
	 * 更新专家信息
	 */
	public void updateExpert() {
		try {
			allExperts.remove(selected);
			selected = expertService.createOrUpdate(selected);
			
			allExperts.add(selected);
			List<DepartmentEntityBean> lt = getAllParentDept(selected);
			expertDeptNameMap.put(selected, lt);
			initTreeTable();
			
			addSuccessMessage("更新成功！");
		} catch (Exception e) {
			addErrorMessage("更新失败！");
			e.printStackTrace();
		}
		
	}
	
	/**
	 * 专家在查询框的显示
	 * @param query
	 * @return
	 */
	public List<InspectionExpert> completeExpert(String query) {
		Set<InspectionExpert> experts = new LinkedHashSet<InspectionExpert>();
		for (InspectionExpert expert : allExperts) {
			String nameHead = PingYinUtil.getPingYinHeader(expert.getName());
			if (nameHead.toLowerCase().contains(query)) {
				experts.add(expert);
			}
			if (expert.getName().contains(query)) {
				experts.add(expert);
			}
		}
		return new ArrayList<InspectionExpert>(experts);
	}
	/**
	 * 查询专家
	 * @throws Exception 
	 */
	public void search() throws Exception{
		if (StringUtils.isNotEmpty(searchExpert) ) {
			treeTableRoot = new LibTreeNode(new ExpertTreeTableDTO(), null);
			String rootName = deptRoots.get(0).getName();
			TreeNode orgRoot = new LibTreeNode("dept", new ExpertTreeTableDTO(rootName), treeTableRoot);
			InspectionExpert expert = findExpert(searchExpert);
			if(null != expert) {
				String deptName = expert.getDeptName();
				ExpertTreeTableDTO newExpertDTO = new ExpertTreeTableDTO(expert.getName(), expert.getCode()
						,expert.getTelephone(), expert.getAddress(),expert.getIntroduce(),expert.getPosition()) ;
				if(!StringUtils.isBlank(deptName)) {
					TreeNode childRoot = new LibTreeNode("dept", new ExpertTreeTableDTO(expert.getDeptName()), orgRoot);
					new DefaultTreeNode("expert", newExpertDTO, childRoot);
				}else {
					new DefaultTreeNode("expert", newExpertDTO, orgRoot);
				}
				orgRoot.setExpanded(true);
			}
		}
	}
	/**
	 * 根据输入框中的信息查询专家
	 * @param str
	 * @return 
	 */
	private InspectionExpert findExpert(String str) {
		InspectionExpert expert = null;
		// 首先根据id查询
		try {
			expert = expertService.findById(str);
			if(null == expert) {
				// 根据名称查询
				expert = expertService.findByName(str);
				if(null == expert) {
					// 根据code查询
					expert = expertService.findByCode(str);
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return expert;
	}
	
	public void alertMessage() {
		List<InspectionStation> stations = stationService.findByExpertCode(selected.getId());
		if(!stations.isEmpty()) {
			 alertMessage = "该专家和变电站有关联关系，确定删除吗？";
		}else {
			 alertMessage = "确定删除吗？";
		}
	}
	
	/**
	 * 删除和变电站专家
	 */
	public void delete() {
		if(selected != null) {
			try {
				String condition = "确定删除吗？";
				if(alertMessage.length()>condition.length()) {
					expertService.delete(selected.getId()); 
				} else {
					expertService.directDelete(selected.getId());
				}
				addSuccessMessage("删除成功");
				expertDeptNameMap.remove(selected);
				allExperts.remove(selected);
				initTreeTable();
				selected = null;
				searchExpert = null;
			} catch (Exception e) {
				addErrorMessage("删除异常");
				e.printStackTrace();
			}
		}else {
			addErrorMessage("请选择一条记录");
		}
	}
	
	/**
	 * 重置查询框
	 */
	public void reset() {
		searchExpert = null;
		initTreeTable();
	}
	/**
	 * 重置人员搜索框
	 */
	public void refresh() {
		initTree();
		personName = "";
		choiceStatus = false;
		checkboxPersons.clear();
	}
	
	/**
	 * 响应新增
	 */
	public void addExpert() {
		personnels = new ArrayList<PersonnelEntityBean>();
		personnels.addAll(PermissionDataCache.getInstance().getPersonMap().values());
		personNameMap = initPersonNameMap(personnels);
		refresh();
	}
	
	
	/**
	 * treeTable选择事件
	 * @param event
	 */
	public void onTreeTableNodeSelect(NodeSelectEvent event) {
		orgSelectedNode = event.getTreeNode();
		if ("dept".equals(orgSelectedNode.getType())) {
			selected = null;
	    } else if ("expert".equals(orgSelectedNode.getType())) {//点击人  右侧依然是部门下的专家列表
	    	 String code = ((ExpertTreeTableDTO) orgSelectedNode.getData()).getCode();
	         for (InspectionExpert expert : allExperts) {
				if(code.equals(expert.getCode())) {
					selected =  expert;
					break;
				}
			} 
		}
	}
	
	/**
	 * 组织机构树查人
	 * @param event
	 */
    public  void autoCompleteOrgTree(SelectEvent event) {
    	Object item = event.getObject();
		if (null != item) {
			filterTree(item.toString());
		}
		choiceStatus = true;
    }
    
	/**
	 * 继续选择 
	 */
	public void addChoice() {
		personName = null;
		choiceStatus = false;
		resetPersonTreeByChoice();
	}
	
	/**
	 * 根据继续选择按钮重构人员树
	 */
	private void resetPersonTreeByChoice() {
        root = resetPersonTreeRoot;
        Set<DepartmentEntityBean> depts = getDeptsByChoicePersons();
        List<TreeNode> nodes = root.getChildren();
        for (TreeNode node : nodes) {
			if("dept".equals(node.getType())) {
				 List<TreeNode> childNodes = node.getChildren();
				 recursionContinueRoot(childNodes,depts);
			}else {
				if(checkboxPersons.contains(node.getData())) {
					node.setSelected(true);
				}
			}
		}
	}
	
	private Set<DepartmentEntityBean> getDeptsByChoicePersons() {
		 Set<DepartmentEntityBean> depts = new HashSet<DepartmentEntityBean>();
		 for (PersonnelEntityBean person : checkboxPersons) {
			List<DepartmentEntityBean> dept = dm.recursiveFindParentDepartments(person);
			depts.addAll(dept);
		 }
		return depts;
	}

	private void recursionContinueRoot(List<TreeNode> childNodes, Set<DepartmentEntityBean> depts) {
		for (TreeNode treeNode : childNodes) {
			if("dept".equals(treeNode.getType()) && depts.contains(  (DepartmentEntityBean) treeNode.getData()) ) {
				treeNode.setExpanded(true);
				onNodeExpand(treeNode,"expand");
				List<TreeNode> treeNodes = treeNode.getChildren();
				recursionContinueRoot(treeNodes,depts);
			}else {
				if(checkboxPersons.contains(treeNode.getData())) {
					treeNode.getParent().setExpanded(true);
					treeNode.setSelected(true);
				}
			}
		}
		
	}
	
	private void onNodeExpand(TreeNode treeNode,String status) {
		TreeNode node = treeNode;
		node.getChildren().clear();
		DepartmentEntityBean dept = (DepartmentEntityBean) node.getData();
		Set<DepartmentEntityBean> ds = dm.findSubDepartments(dept.getId());
		List<PersonnelEntityBean> personnels = dm.findDeptPersonnels(dept.getId());
		if("expand".equals(status)) {
			for (DepartmentEntityBean d : ds) {
				new LibTreeNode("dept", d, node);
			}
			if (personnels != null && personnels.size() > 0) {
				for (PersonnelEntityBean p : personnels) {
					new DefaultTreeNode("personnel", p, node);
				}
			}
		}else if("select".equals(status)){
			if(choiceStatus!=true) {//查询以后不走这步  不需要展开节点
				for (DepartmentEntityBean d : ds) {
					TreeNode n =  new LibTreeNode("dept", d, node);
					n.setSelected(true);
					onNodeExpand(n,"select");
				}
			}
			if (personnels != null && personnels.size() > 0) {
				for (PersonnelEntityBean p : personnels) {
				DefaultTreeNode n = new DefaultTreeNode("personnel", p, node);
				if(choiceStatus==true && checkboxPersons.contains(p)) {//查询以后    
					n.setSelected(true);
				}else if(choiceStatus == false){//不查询  全都添加  并且选择
					checkboxPersons.add(p);
					n.setSelected(true);
					parentSetSelected(node);
				}
			  }
			}
		}
	}
	/**
	 * 子被选 父就被选
	 * @param node
	 */
	private void parentSetSelected(TreeNode node) {
		if(node.getParent()!=null) {
			node.getParent().setSelected(true);
			TreeNode treeNode =	node.getParent();
			parentSetSelected(treeNode);
		}
	}
	
	/**
	 * 组织机构树选择  专家
	 * @param event
	 */
	public void onNodeSelect(NodeSelectEvent event) {
		TreeNode node = event.getTreeNode();
		if("dept".equals(node.getType())) {
			List<TreeNode> nodes = node.getChildren();
			recursionNodes(nodes);
			onNodeExpand(node,"select");
		} else {
			checkboxPersons.add((PersonnelEntityBean) node.getData());
		}
	}

	public void onNodeUnSelect(NodeUnselectEvent event) {
		TreeNode node = event.getTreeNode();
		 node.setSelected(false);
		List<PersonnelEntityBean> persons = new ArrayList<PersonnelEntityBean>();
		if("dept".equals(node.getType())) {
			List<TreeNode> nodes = node.getChildren();
			recursionRemoveNodes(nodes,persons);
		} else {
			persons.add((PersonnelEntityBean) node.getData());
		}
		checkboxPersons.removeAll(persons);
	}
	
	/**
	 * 递归添加
	 * @param nodes
	 */
    private void recursionNodes(List<TreeNode> nodes) {
		for (TreeNode treeNode : nodes) {
			if("dept".equals(treeNode.getType())) {
				List<TreeNode> treeNodes = treeNode.getChildren();
				recursionNodes(treeNodes);
			} else {
				checkboxPersons.add((PersonnelEntityBean) treeNode.getData());
			}
		}
	}
	/**
	 * 递归移除
	 * @param nodes
	 * @param persons
	 */
	private void recursionRemoveNodes(List<TreeNode> nodes, List<PersonnelEntityBean> persons) {
		for (TreeNode treeNode : nodes) {
			treeNode.setSelected(false);
			if("dept".equals(treeNode.getType())) {
				List<TreeNode> treeNodes = treeNode.getChildren();
				recursionRemoveNodes(treeNodes,persons);
			}else {
				persons.add((PersonnelEntityBean) treeNode.getData());
			}
		}
				
	}
	
	public TreeNode getRoot() {
		return root;
	}

	public void setRoot(TreeNode root) {
		this.root = root;
	}

	public List<PersonnelEntityBean> getPersonnels() {
		return personnels;
	}
	public void setPersonnels(List<PersonnelEntityBean> personnels) {
		this.personnels = personnels;
	}

	public TreeNode getOrgSelectedNode() {
		return orgSelectedNode;
	}
	public void setOrgSelectedNode(TreeNode orgSelectedNode) {
		this.orgSelectedNode = orgSelectedNode;
	}
	public InspectionExpert getSelected() {
		return selected;
	}
	public void setSelected(InspectionExpert selected) {
		this.selected = selected;
	}

	public String getPersonName() {
		return personName;
	}

	public void setPersonName(String personName) {
		this.personName = personName;
	}

	public TreeNode getTreeTableRoot() {
		return treeTableRoot;
	}

	public void setTreeTableRoot(TreeNode treeTableRoot) {
		this.treeTableRoot = treeTableRoot;
	}

	public boolean isChoiceStatus() {
		return choiceStatus;
	}

	public void setChoiceStatus(boolean choiceStatus) {
		this.choiceStatus = choiceStatus;
	}

	public Set<PersonnelEntityBean> getCheckboxPersons() {
		return checkboxPersons;
	}

	public void setCheckboxPersons(Set<PersonnelEntityBean> checkboxPersons) {
		this.checkboxPersons = checkboxPersons;
	}

	public String getAlertMessage() {
		return alertMessage;
	}

	public void setAlertMessage(String alertMessage) {
		this.alertMessage = alertMessage;
	}

	public String getSearchExpert() {
		return searchExpert;
	}

	public void setSearchExpert(String searchExpert) {
		this.searchExpert = searchExpert;
	}

}
